package net.dotool;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author 李岩飞
 * @email eliyanfei@126.com 2018年1月18日 下午1:56:59
 * 
 */
public class DateTools {

	private static final Map<String, SimpleDateFormat> SDFS = new HashMap<String, SimpleDateFormat>(4);
	private static final Lock lockSdf = new ReentrantReadWriteLock().writeLock();

	protected static final SimpleDateFormat getSdf(final String pattern) {
		SimpleDateFormat sdf = SDFS.get(pattern);
		if (null != sdf)
			return sdf;
		lockSdf.lock();
		try {
			sdf = SDFS.get(pattern);
			if (null == sdf)
				SDFS.put(pattern, sdf = new SimpleDateFormat(pattern));
		} finally {
			lockSdf.unlock();
		}
		return sdf;
	}

	public static synchronized Date toDate(final String value, final String pattern) {
		try {
			return null == value ? null : getSdf(pattern).parse(value);
		} catch (final ParseException e) {
			return null;
		}
	}

	public static synchronized String formatDate(final Date value, final String pattern) {
		return value == null ? "" : getSdf(pattern).format(value);
	}

	public static int formatDateNum(String value, String pattern, String type, int delay) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(DateTools.toDate(value, pattern));
		if ("h".equals(type)) {
			cal.add(Calendar.HOUR_OF_DAY, delay);
			pattern = "yyyyMMddHH";
		} else if ("d".equals(type)) {
			cal.add(Calendar.DATE, delay);
			pattern = "yyyyMMdd";
		} else if ("w".equals(type)) {
			return getWeek(value, pattern, delay);
		} else if ("m".equals(type)) {
			cal.add(Calendar.MONTH, delay);
			pattern = "yyyyMM";
		}
		return NumberTools.toInt(formatDate(cal.getTime(), pattern), 0);
	}

	/**
	 * 获取一年的第几周
	 */
	public static int getWeek(String value, String pattern, int delay) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(DateTools.toDate(value, pattern));
		cal.add(Calendar.WEEK_OF_YEAR, delay);
		int lastWeek = cal.get(Calendar.YEAR) * 100 + cal.get(Calendar.WEEK_OF_YEAR);
		return lastWeek;
	}

	public static List<String> getDifferHour(final String startDate, final String endDate, final String pattern) {
		final List<String> tablePrefix = new ArrayList<String>();
		final Date start = toDate(startDate, pattern);
		final Date end = toDate(endDate, pattern);
		final GregorianCalendar startCalendar = new GregorianCalendar();
		final GregorianCalendar endCalendar = new GregorianCalendar();
		startCalendar.setTime(start);
		endCalendar.setTime(end);
		while (startCalendar.before(endCalendar)) {
			tablePrefix.add(formatDate(startCalendar.getTime(), pattern));
			startCalendar.add(Calendar.HOUR_OF_DAY, 1);
		}
		tablePrefix.add(formatDate(endCalendar.getTime(), pattern));
		return tablePrefix;
	}

	public static List<String> getDifferDay(final String startDate, final String endDate, final String pattern) {
		final List<String> tablePrefix = new ArrayList<String>();
		final Date start = toDate(startDate, pattern);
		final Date end = toDate(endDate, pattern);
		final GregorianCalendar startCalendar = new GregorianCalendar();
		final GregorianCalendar endCalendar = new GregorianCalendar();
		startCalendar.setTime(start);
		endCalendar.setTime(end);
		while (startCalendar.before(endCalendar)) {
			tablePrefix.add(formatDate(startCalendar.getTime(), pattern));
			startCalendar.add(Calendar.DATE, 1);
		}
		tablePrefix.add(formatDate(endCalendar.getTime(), pattern));
		return tablePrefix;
	}

	public static int toDateNum(final Date date, final String pattern) {
		return Integer.valueOf(formatDate(date, pattern));
	}

	public static long getDateNum(int type, int delay, String format) {
		Calendar cal = Calendar.getInstance();
		cal.add(type, delay);
		return NumberTools.toLong(formatDate(cal.getTime(), format), 0);
	}

	public static String getDate(int delay) {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.HOUR_OF_DAY, -delay);
		return formatDate(cal.getTime(), "yyyy-MM-dd HH");
	}

	public static String getDate(int type, int delay, String format) {
		Calendar cal = Calendar.getInstance();
		cal.add(type, delay);
		return formatDate(cal.getTime(), format);
	}

	/**
	 * @return 今年
	 */
	public static int thisYear() {
		return Calendar.getInstance().get(Calendar.YEAR);
	}

	/**
	 * @return 当前月份
	 */
	public static int thisMonth() {
		return Calendar.getInstance().get(Calendar.MONTH);
	}

	/**
	 * 是否闰年
	 * 
	 * @param year
	 *            年
	 * @return 是否闰年
	 */
	public static boolean isLeapYear(int year) {
		return new GregorianCalendar().isLeapYear(year);
	}
}
